package org.apache.roller.weblogger.ui.rendering.model;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.roller.weblogger.WebloggerException;
import org.apache.roller.weblogger.business.WeblogEntryManager;
import org.apache.roller.weblogger.business.WebloggerFactory;
import org.apache.roller.weblogger.pojos.*;
import org.apache.roller.weblogger.pojos.wrapper.WeblogWrapper;
import org.apache.roller.weblogger.ui.rendering.util.WeblogPageRequest;
import org.apache.roller.weblogger.ui.rendering.util.WeblogRequest;

import javax.servlet.jsp.PageContext;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by satish on 2/6/15.
 */
public class ArchiveModel implements Model {

    private static Log log = LogFactory.getLog(ArchiveModel.class);

    private PageContext pageContext;
    private WeblogPageRequest pageRequest;
    private List<WeblogEntry> weblogEntries;
    private List<TagStat> tags;
    private Map<String, Integer> categoryMap;

    @Override
    public String getModelName() {
        return "archiveModel";
    }

    @Override
    public void init(Map initData) throws WebloggerException {

        // extract page context
        this.pageContext = (PageContext) initData.get("pageContext");

        // we expect the init data to contain a weblogRequest object
        WeblogRequest weblogRequest = (WeblogRequest) initData.get("parsedRequest");
        if(weblogRequest == null) {
            throw new WebloggerException("expected weblogRequest from init data");
        }

        // ArchiveModel only works on page requests, so cast weblogRequest
        // into a WeblogPageRequest and if it fails then throw exception
        if(weblogRequest instanceof WeblogPageRequest) {
            this.pageRequest = (WeblogPageRequest) weblogRequest;
        } else {
            throw new WebloggerException("weblogRequest is not a WeblogPageRequest."+
                    "  ArchiveModel only supports page requests.");
        }

        initArchive();
    }

    private void initArchive() throws WebloggerException {
        WeblogEntryManager mgr = WebloggerFactory.getWeblogger().getWeblogEntryManager();
        WeblogEntrySearchCriteria wesc = new WeblogEntrySearchCriteria();
        Weblog weblog = this.pageRequest.getWeblog();
        wesc.setWeblog(weblog);
        wesc.setStatus(WeblogEntry.PubStatus.PUBLISHED);
        wesc.setLocale(this.pageRequest.getLocale());

        weblogEntries = mgr.getWeblogArchives(wesc);

        tags = mgr.getTags(weblog, null, null, 0, -1);
    }

    public List<ArchiveEntry> getArchiveEntriesByDate(WeblogWrapper websiteWrapper) {
        List<ArchiveEntry> archiveEntries = new ArrayList<ArchiveEntry>();
        Map<String, Integer> dateMap = new HashMap<String, Integer>();
        categoryMap = new HashMap<String, Integer>();

        SimpleDateFormat displayDateFormat = new SimpleDateFormat("MMMMM yyyy");
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMM");

        for(WeblogEntry weblogEntry : weblogEntries) {
            String displayDate = displayDateFormat.format(weblogEntry.getPubTime());
            String date = dateFormat.format(weblogEntry.getPubTime());

            String key = date + "~" + displayDate;
            Integer entriesCount = dateMap.get(key);
            if(entriesCount == null) {
                entriesCount = 1;
            } else {
                entriesCount++;
            }
            dateMap.put(key, entriesCount);

            String name = weblogEntry.getCategory().getName();
            Integer categoryCount = categoryMap.get(name);
            if(categoryCount == null) {
                categoryCount = 1;
            } else {
                categoryCount++;
            }
            categoryMap.put(name, categoryCount);
        }

        for (Map.Entry<String, Integer> entry : dateMap.entrySet()) {
            ArchiveEntry archiveEntry = new ArchiveEntry();
            String[] dates = entry.getKey().split("~");
            archiveEntry.setDate(dates[0]);
            archiveEntry.setDisplayDate(dates[1]);
            archiveEntry.setEntriesCount(entry.getValue());
            archiveEntries.add(archiveEntry);
        }
        Collections.sort(archiveEntries, new Comparator<ArchiveEntry>() {
            @Override
            public int compare(ArchiveEntry o1, ArchiveEntry o2) {
                return -(o1.getDate().compareTo(o2.getDate()));
            }
        });
        return archiveEntries;
    }

    public List<TagStat> getTags() {
        return tags;
    }

    public List<String> getCategories() {
        List<String> categoryNames = new ArrayList<String>(categoryMap.keySet());
        Collections.sort(categoryNames);
        return categoryNames;
    }

    public Integer getCategoryCount(String name) {
        return categoryMap.get(name);
    }

    public List<WeblogEntry> getRecentEntries(int count) {
        int numOfEntries = weblogEntries.size();
        if(count > numOfEntries) {
            count = numOfEntries;
        }
        Collections.sort(weblogEntries, new Comparator<WeblogEntry>() {
            @Override
            public int compare(WeblogEntry o1, WeblogEntry o2) {
                return o2.getPubTime().compareTo(o1.getPubTime());
            }
        });

        List<WeblogEntry> returnList = new ArrayList<WeblogEntry>(count);
        for(int i=0; i<count; i++) {
            returnList.add(weblogEntries.get(i));
        }
        return returnList;
    }
}